package ua.kiev.tosik.price.modules.clients.gui.prices;

import org.apache.log4j.Logger;
import org.jdesktop.swingx.JXErrorPane;
import org.jdesktop.swingx.error.ErrorInfo;
import ua.kiev.tosik.price.models.Clients;
import ua.kiev.tosik.price.models.PricesFiles;
import ua.kiev.tosik.price.modules.clients.conf.ModuleConfig;
import ua.kiev.tosik.price.modules.clients.database.files.PricesFilesDeleteAllWorker;
import ua.kiev.tosik.price.modules.clients.database.files.PricesFilesDeleteWorker;
import ua.kiev.tosik.price.modules.clients.database.files.PricesFilesLoadWorker;
import ua.kiev.tosik.price.modules.clients.database.files.PricesFilesUploadWorker;
import ua.kiev.tosik.price.modules.clients.database.prices.PricesDeleteWorker;
import ua.kiev.tosik.price.modules.clients.gui.EditorDialog;
import ua.kiev.tosik.price.modules.clients.gui.MainPanel;
import ua.kiev.tosik.price.modules.clients.gui.files.PricesFilesStatusBar;
import ua.kiev.tosik.price.modules.clients.gui.files.preview.PricesFilesPreviewPanel;
import ua.kiev.tosik.price.modules.clients.gui.files.upload.FilesDialog;
import ua.kiev.tosik.price.modules.clients.tools.ExcelParserWorker;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Date;
import java.util.List;

public class PricesDialog implements PropertyChangeListener {

	private static Logger logger = Logger.getLogger("ua.kiev.tosik.price.modules.clients.gui.files");
	private static PricesDialog ourInstance;
	private JDialog dialog;
	private ModuleConfig config;
	// private ActionListener closeAction;
	private boolean lockDialog = false;
	private PricesToolBar toolBar;
	private PricesCenterPanel centerPanel;
	private Clients clients;
	private FilesDialog filesDialog;
	private PricesFilesStatusBar statusBar;

	private static final Dimension D_SIZE;
	static {
		D_SIZE = new Dimension(800, 480);
	}

	public static PricesDialog getInstance() {
		if ( ourInstance == null ) {
			ourInstance = new PricesDialog();
		}
		return ourInstance;
	}

	public static void destroy() {
		ourInstance = null;
	}

	private PricesDialog() {
		logger.debug("Initialize Prices Dialog");
		config = ModuleConfig.getInstance();
		ActionListener closeAction = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				close();
			}
		};
		dialog = new JDialog(EditorDialog.getInstance().getDialog());
		dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
		dialog.getRootPane().registerKeyboardAction(closeAction, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
		dialog.setModal(true);
		dialog.setTitle(config.get("clients.editor.prices.title"));
		dialog.setIconImage( new ImageIcon(config.get("clients.editor.prices.icon")).getImage() );
		dialog.setResizable(false);
		dialog.setSize(D_SIZE);
		dialog.setLayout( new BorderLayout() );
		dialog.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent ev) {
				close();
			}
		});

		// panel = new JPanel( new BorderLayout() );

		toolBar = new PricesToolBar(this);
		centerPanel = new PricesCenterPanel();
		statusBar = new PricesFilesStatusBar();

		dialog.add(toolBar.getToolBar(), BorderLayout.NORTH);
		dialog.add(centerPanel.getCenterPanel(), BorderLayout.CENTER);
		dialog.add(statusBar.getStatusBar(), BorderLayout.SOUTH);

		// dialog.add(panel, BorderLayout.CENTER);

		/*
		lockableUI = new LockableUI();
		layer = new JXLayer<JComponent>(panel, lockableUI);
		lockableUI.setLocked(false);
		*/
		// loadPricesFiles();
	}

	public void loadPricesFiles() {
		if ( clients == null ) {
			logger.error("Can't load files files for client NULL!");
			return;
		}
		PricesFilesLoadWorker loadWorker = new PricesFilesLoadWorker();
		loadWorker.setClients(clients);
		loadWorker.addPropertyChangeListener(this);
		loadWorker.execute();
	}

	public JDialog getDialog() {
		return dialog;
	}

	public PricesFilesStatusBar getStatusBar() {
		return statusBar;
	}

	public PricesCenterPanel getCenterPanel() {
		return centerPanel;
	}

	public void open() {
		dialog.setSize(D_SIZE);
		dialog.setLocationRelativeTo(MainPanel.getInstance().getPanel());
		dialog.setVisible(true);
	}

	public void close() {
		if ( !lockDialog ) {
			dialog.setVisible(false);
			dialog.dispose();
			setClients(null);
			logger.debug("PricesDialog closed");
		}
	}

	public void setLockDialog(boolean lockDialog) {
		this.lockDialog = lockDialog;
		toolBar.setEnableButtons(!lockDialog);
		// centerPanel.lockPanel(lockDialog);
	}

	public void setClients(Clients clients) {
		if ( clients != null && clients != this.clients ) {
			this.clients = clients;
			centerPanel.removeAllTabs();
			centerPanel.getFilesPanel().getTable().getModel().clear();
			loadPricesFiles();
		}
	}

	@Override
	@SuppressWarnings("unchecked")
	public void propertyChange(PropertyChangeEvent evt) {
		final String pName = evt.getPropertyName();

		if ( pName.endsWith("_START") ) {
			setLockDialog(true);
		}
		if ( pName.endsWith("_DONE") || pName.endsWith("_OK") ) {
			setLockDialog(false);
		}

		if ( pName.equals("FILE_DELETE_OK") ) {
			int rowIndex = (Integer)evt.getNewValue();
			centerPanel.getFilesPanel().getTable().getModel().removeRow(rowIndex);
		}
		if ( pName.equals("FILE_DELETE_ALL_OK") ) {
			centerPanel.removeAllTabs();
			centerPanel.getFilesPanel().getTable().getModel().clear();
			loadPricesFiles();
		}
		if ( pName.equals("FILE_LOAD_OK") ) {
			List<PricesFiles> dataList = (List<PricesFiles>)evt.getNewValue();
			centerPanel.getFilesPanel().getTable().getModel().addRowSet(dataList);
		}

		if ( pName.equals("FILE_UPLOAD_DONE") ) {
			filesDialog.enableForm(true);
			filesDialog.setLockDialog(false);
		}
		if ( pName.equals("FILE_UPLOAD_OK") ) {
			filesDialog.close();
			PricesFiles pricesFiles = (PricesFiles)evt.getNewValue();
			centerPanel.getFilesPanel().getTable().getModel().addRow(pricesFiles);
		}
		if ( pName.equals("PRICE_CLEAR_OK") ) {
			PricesFiles pf = (PricesFiles)evt.getNewValue();
			int rowIndex = (Integer)evt.getOldValue();
			if ( pf != null && rowIndex >= 0 ) {
				centerPanel.getFilesPanel().getTable().getModel().updateRow(rowIndex, pf);
			}
		}
		if ( pName.endsWith("_ERROR") ) {
			Exception e = (Exception)evt.getNewValue();
			String title = config.get("clients.editor.message.error");
			String message = e.getLocalizedMessage();
			String details = e.getLocalizedMessage();
			showMessageDialog(title, message, details);
			logger.error(e.getMessage(), e);
		}
	}

	public void showMessageDialog(String title, String message, String details) {
		ErrorInfo errorInfo = new ErrorInfo(title, message, details, "ErrorMessage", null, null, null);
		JXErrorPane.showDialog(getDialog(), errorInfo);
	}

	public void openFileUploadDialog(final File newFile) {
		if ( filesDialog == null ) {
			filesDialog = new FilesDialog(dialog);
		}
		filesDialog.setClients(clients);
		filesDialog.setFile(newFile);
		filesDialog.setUploadAction( new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				uploadPricesFile(clients, newFile, filesDialog.getFileDate());
			}
		});
		filesDialog.open();
	}

	public void uploadPricesFile(Clients clients, File file, Date fileDate) {
		logger.debug("Try to upload file: " + file.getName() + " (" + (file.length()/1024) + " Kb), Date: " + fileDate);
		if ( clients == null ) {
			logger.debug("Client is not defined for prices file upload");
			return;
		}
		if ( file.length() == 0 ) {
			logger.debug("File size = 0 for prices file upload");
			return;
		}
		if ( fileDate == null ) {
			logger.debug("File date is not defined for prices file upload");
			return;
		}

		filesDialog.enableForm(false);
		filesDialog.setLockDialog(true);

		PricesFilesUploadWorker uploadWorker = new PricesFilesUploadWorker();
		uploadWorker.setClients(clients);
		uploadWorker.setFile(file);
		uploadWorker.setFileDate(fileDate);
		uploadWorker.addPropertyChangeListener(this);
		uploadWorker.addPropertyChangeListener(statusBar);
		uploadWorker.execute();
	}

	public void deletePricesFiles(PricesFiles pricesFiles, int rowIndex) {
		logger.debug("Try to delete PricesFiles: " + pricesFiles.getFileName());
		String uniqueId = pricesFiles.getFileName() + " (" + pricesFiles.getFileSize() + "), ID: " + pricesFiles.getId();
		centerPanel.removeTabById(uniqueId);
		PricesFilesDeleteWorker deleteWorker = new PricesFilesDeleteWorker();
		deleteWorker.setPricesFiles(pricesFiles);
		deleteWorker.setRowIndex(rowIndex);
		deleteWorker.addPropertyChangeListener(this);
		deleteWorker.addPropertyChangeListener(statusBar);
		deleteWorker.execute();
	}

	public void deletePricesFilesAll() {
		int res = JOptionPane.NO_OPTION;
		try {
			res = JOptionPane.showConfirmDialog(dialog, config.get("clients.files.deleteAll.text"), config.get("clients.files.table.deleteRow.text"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, new ImageIcon(config.get("clients.files.table.deleteRow.icon")));
		} catch (Exception e) {
			logger.warn(e.getLocalizedMessage());
		}
		if (res == JOptionPane.YES_OPTION) {
			PricesFilesDeleteAllWorker deleteWorker = new PricesFilesDeleteAllWorker();
			deleteWorker.setClients(this.clients);
			deleteWorker.addPropertyChangeListener(this);
			deleteWorker.addPropertyChangeListener(statusBar);
			deleteWorker.execute();
		}
	}

	public void clearPrices(PricesFiles pricesFiles, int rowIndex) {
		logger.debug("Deleting prices for: " + pricesFiles.getFileName());
		PricesDeleteWorker deleteWorker = new PricesDeleteWorker();
		deleteWorker.setRowIndex(rowIndex);
		deleteWorker.setPricesFiles(pricesFiles);
		deleteWorker.addPropertyChangeListener(this);
		deleteWorker.addPropertyChangeListener(statusBar);
		deleteWorker.execute();
	}

	public void createRawPreview(int selectedRow) { 
		PricesFiles pricesFiles = centerPanel.getFilesPanel().getTable().getModel().getRow(selectedRow);
		if ( pricesFiles.isParsed() ) {
			return;
		}
		String uniqueId = pricesFiles.getFileName() + " (" + pricesFiles.getFileSize() + "), ID: " + pricesFiles.getId();
		if ( !centerPanel.isTabExists(uniqueId) ) {
			PricesFilesPreviewPanel previewPanel = new PricesFilesPreviewPanel();
			previewPanel.setPricesFiles(pricesFiles);
			centerPanel.addTab(uniqueId, previewPanel);
			ExcelParserWorker parserWorker = new ExcelParserWorker(pricesFiles);
			parserWorker.addPropertyChangeListener(previewPanel);
			parserWorker.execute();
		}
	}

}
